﻿#include "linux_list.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct person {
  int age;
  char name[20];
  struct list_head list;
};

// linux 内核中双向循环链表中最重要的就是offsetof宏 和 container_of 宏
// 这两个宏实现原理是 list 能够正常工作的关键

int main(int argc, char *argv[]) {

  struct person person_head;
  //初始化双链表表头
  INIT_LIST_HEAD(&person_head.list);

  struct person *p_person;
  int i;
  // 添加节点
  for (i = 0; i < 5; i++) {
    p_person = (struct person *)malloc(sizeof(struct person));
    p_person->age = (i + 1) * 10;
    // 将格式化的字符串写入name
    snprintf(p_person->name, sizeof(p_person->name), "name%d", i + 1);
    // 将节点链接到链表的末尾
    // 如果想把节点链接到链表的表头后面，则使用 list_add
    list_add_tail(&(p_person->list), &(person_head.list));
  }

  struct list_head *cur_node, *next;

  // 遍历链表
  printf("==== 1st iterator double-link ====\n");
  list_for_each(cur_node, &person_head.list) {
    // （当前节点指针，数据结构， 数据结构中的属性）
    p_person = list_entry_lnx(cur_node, struct person, list);
    printf("name:%-2s, age:%d\n", p_person->name, p_person->age);
  }

  // 删除节点age为20的节点
  printf("==== delete node(age:20) ====\n");
  // （当前节点指针， 存放下一个元素的节点指针 ， 列表对象地址）
  list_for_each_safe(cur_node, next, &person_head.list) {
    p_person = list_entry_lnx(cur_node, struct person, list);
    if (p_person->age == 20) {
      list_del_init(cur_node);
      free(p_person);
    }
  }

  // 再次遍历链表
  printf("==== 2nd iterator double-link ====\n");
  list_for_each(cur_node, &person_head.list) {
    p_person = list_entry_lnx(cur_node, struct person, list);
    printf("name:%-2s, age:%d\n", p_person->name, p_person->age);
  }

  // 释放资源
  list_for_each_safe(cur_node, next, &person_head.list) {
    p_person = list_entry_lnx(cur_node, struct person, list);
    list_del_init(cur_node);
    free(p_person);
  }

  return 0;
}